import { location } from "../utils/getLocation";
import { guiMover } from "../utils/gui";
import settings from "../utils/settings";
import { DrawString, getItemSBID, newItemStackFrom } from "../utils/utils";

class QuiverManager {
    constructor() {
        this.quivers = {};
        this.quiver = {};
        this.readFile();
        this.registerTriggers();
        this.registerRenderTrigger();
    }

    readFile() {
        try {
            if(!FileLib.exists("./config/ChatTriggers/modules/BabyzombieAddons/config/quiver.json")) return;
            const data = FileLib.read("./config/ChatTriggers/modules/BabyzombieAddons/config/quiver.json");
            this.quivers = JSON.parse(data);
            this.quiver = this.quivers[location.SBProfile] || {};
        } catch (e) {}
    }

    saveFile() {
        this.quivers[location.SBProfile] = this.quiver;
        FileLib.write("./config/ChatTriggers/modules/BabyzombieAddons/config/quiver.json", JSON.stringify(this.quivers, null, 4), true);
    }

    setArrow(arrowName, amount) {
        if(this.quiver.quiver == null) this.quiver.quiver = {};
        this.quiver.quiver[arrowName] = parseInt(amount);
    }
    
    getArrow(arrowName = "") {
        const amount = this.quiver.quiver[arrowName || this.quiver.current] || 0;
        return amount;
    }

    registerTriggers() {
        register("worldUnload", () => { this.saveFile(); });
        register("gameUnload", () => { this.saveFile(); });
        location.registerProfileSwitchTrigger(() => {
            this.saveFile();
            this.quiver = this.quivers[location.SBProfile] || {};
        });  

        register("chat", (arrowName,event) => {
            if(!location.inSkyblock) return;
            if(arrowName != "None") this.quiver.current = arrowName;
            this.quiver.selected = arrowName;
        }).setChatCriteria("You set your selected arrow type to ${arrowName}!");

        register("tick", () => {
            if(!location.inSkyblock) return;
            let heldItem = Player.getHeldItem();
            if(heldItem == null || heldItem.getID() != 261) return;
            let arrowItem = Player.getInventory().getStackInSlot(8);
            if(arrowItem == null || !(arrowItem.getID() == 288 || arrowItem.getID() == 262) || !arrowItem.getName().removeFormatting().startsWith("Quiver")) {
                arrowItem = Player.getInventory().getStackInSlot(9);
                if(arrowItem == null || !(arrowItem.getID() == 288 || arrowItem.getID() == 262) || !arrowItem.getName().removeFormatting().startsWith("Quiver")) return;
            };
            let lore = arrowItem.getLore().find(l => l.removeFormatting().startsWith("Active Arrow: "));
            if(lore == null) return;
            let arrowName = lore.removeFormatting().replace("Active Arrow: ", "").replace(/ \([0-9,]+\)/,"");
            let arrowAmout = lore.removeFormatting().replace("Active Arrow: ", "").replace(/[^0-9]/g,"");
            this.setArrow(arrowName, arrowAmout);
            this.quiver.current = arrowName;
        });

        register("chat", (amount,event) => {
            if(!location.inSkyblock) return;
            this.setArrow("Flint Arrow", this.getArrow("Flint Arrow") + parseInt(amount));
            if(this.quiver.selected != "None" && this.getArrow(this.quiver.selected) > 0) this.quiver.current = this.quiver.selected;
        }).setChatCriteria("You filled your quiver with ${amount} extra arrows!");

        register("chat", (arrowName,amount) => {
            if(!location.inSkyblock) return;
            this.setArrow(arrowName, this.getArrow(arrowName) + parseInt(amount));
            if(this.quiver.selected != "None" && this.getArrow(this.quiver.selected) > 0) this.quiver.current = this.quiver.selected;
        }).setChatCriteria(/Jax forged ([a-zA-Z_ -]+) x([0-9,]+)( for [0-9,]+ Coins|)!/);

        register("chat", () => {
            if(!location.inSkyblock) return;
            for (let key in this.quiver.quiver) {
                delete this.quiver.quiver[key];
            }
        }).setChatCriteria("Cleared your quiver!");

        register("chat", (arrowName) => {
            if(!location.inSkyblock) return;
            this.setArrow(arrowName, 0);
        }).setChatCriteria("QUIVER! You have run out of ${arrowName}s!");


        let LastGuiOpen = 0;
        register("guiOpened", () => {
            if(!location.inSkyblock) return;
            getQuiverGui.register();
            LastGuiOpen = Date.now();
        })
        register("worldLoad",()=>{
            getQuiverGui.unregister();
            LastGuiOpen = Date.now();
        })
        register("step", () => {
            if(LastGuiOpen + 2000 < Date.now()) getQuiverGui.unregister();
        })

        const getQuiverGui = register("renderItemIntoGui", (item,x,y,event) => {
            if(!location.inSkyblock || item.getName().removeFormatting() != "Go Back") return;
            let gui = Player.getContainer();
            if(!gui || gui.getName().removeFormatting() != "Quiver") return;
            let ArrowList = {};
            gui.getItems().slice(0,gui.getSize() - 9 - 36).filter(i => i && [262,409,341,378].indexOf(i.getID()) != -1).forEach(arrow => {
                if(ArrowList[arrow.getName().removeFormatting()] == null) ArrowList[arrow.getName().removeFormatting()] = 0;
                ArrowList[arrow.getName().removeFormatting()] += arrow.getStackSize();
            });
            for (let key in this.quiver.quiver) {
                delete this.quiver.quiver[key];
            }
            for (let arrow in ArrowList) {
                this.setArrow(arrow, ArrowList[arrow]);
            }
            if(this.quiver.selected != "None" && this.getArrow(this.quiver.selected) > 0) this.quiver.current = this.quiver.selected;
            this.saveFile();
            getQuiverGui.unregister();
        })
    }

    renderArrow(x,y,s,arrowName,string) {
        let itemType = "arrow";
        let itemID = arrowName.toUpperCase().replace(/[ -]/g, "_");
        let ench = false;
        if(arrowName == "Flint Arrow") itemID = "ARROW";
        else if(!arrowName.includes("Arrow")) {
            itemType = arrowName.replace(" ", "_").toLowerCase();
            if(itemType == "slimeball") {
                itemType = "slime_ball";
                itemID = "SLIME_BALL";
            }
        } else ench = true;
        let item = new Item(newItemStackFrom("minecraft:" + itemType, 0, `{HideFlags: 254,${(ench?"ench: [],":"")}ExtraAttributes: {id: \"${itemID}\"}}`));

        item.draw(x,y,s);
        DrawString(string, x + 18 * s, y + 3 * s, s, true);
    }

    registerRenderTrigger() {
        register("renderOverlay", () => {
            if(!settings.ShowArrows) return;
            if(guiMover.gui.isOpen()) {
                let x = guiMover.settings.quiver.x;
                let y = guiMover.settings.quiver.y;
                let s = guiMover.settings.quiver.s;
                this.renderArrow(x,y,s,"Flint Arrow","§a114§7x §aFlint Arrow");
                return;
            }
            if(!location.inSkyblock) return;
            let x = guiMover.settings.quiver.x;
            let y = guiMover.settings.quiver.y;
            let s = guiMover.settings.quiver.s;
            let h = 16 * s;

            if(getItemSBID(Player.getHeldItem()) == "ARROW_SWAPPER") {
                let arrows = [];
                for (let arrow in this.quiver.quiver) {
                    if (Object.prototype.hasOwnProperty.call(this.quiver.quiver, arrow)) {
                        if(this.getArrow(arrow) > 0 || arrow == this.quiver.selected) arrows.push(arrow);
                    }
                }
                if(arrows.length == 0) {
                    this.renderArrow(x,y,s,"Flint Arrow","§cNo Arrows :(")
                    return;
                }
                let up = y + h * arrows.length < Renderer.screen.getHeight();
                arrows.forEach((a,i) => {
                    this.renderArrow(x, (up ? y + h * i : y - h * i),s, a,"§" + (this.getArrow(a) > 100 ? "a" : (this.getArrow(a) > 50 ? "e" : "c")) + this.getArrow(a) + "§7x §" + (this.quiver.selected == a ? "a" : "e") + a + (this.quiver.selected == a ? " §a←" : ""));
                })
                return;
            }

            if(this.quiver.selected != "None" && this.getArrow(this.quiver.selected) <= 0 && this.quiver.selected != this.quiver.current) {
                this.renderArrow(x, (y + h * 2 > Renderer.screen.getHeight() ? y - h : y + h), s, this.quiver.selected,"§c0" + "§7x §c" + this.quiver.selected);
            }
            this.renderArrow(x,y,s, this.quiver.current,"§" + (this.getArrow() > 100 ? "a" : (this.getArrow() > 50 ? "e" : "c")) + this.getArrow() + "§7x §" + (this.getArrow() > 100 ? "a" : (this.getArrow() > 50 ? "e" : "c")) + this.quiver.current);
        })
    }
}

export default new QuiverManager();